-
-
Notifications
You must be signed in to change notification settings - Fork 278
useWatch selector init #762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useWatch selector init #762
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough本次变更在示例与核心逻辑两处更新:示例增加一个基于依赖函数的本地 useWatch 用法与调试输出;核心 hook(useWatch)在初始化时支持当 dependencies 为函数时用 dependencies({}) 结果作为初始值,其它行为保持不变。 Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant F as Form
participant UW as useWatch
participant D as dependencies(fn)
participant S as State
U->>F: 打开示例页面
F->>UW: 初始化 useWatch(dependencies)
alt dependencies 是函数
UW->>D: 调用 dependencies({})
D-->>UW: 返回初始派生值
UW->>S: setState(派生值)
else 非函数/未提供
UW->>S: setState(undefined)
end
note over F,UW: 表单交互触发值变化
F->>UW: triggerUpdate(allValues/values, preserve)
UW->>UW: 选择 allValues ?? getFieldsValue(true) 或 values ?? getFieldsValue()
UW->>S: setState(新值)
UW-->>F: 返回最新 watch 值
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Poem
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. ✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @crazyair, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request improves the useWatch hook by ensuring that its selector function is invoked during the initial render, providing a more robust and predictable initial value for watched form fields. This change enhances the hook's reliability and is accompanied by an updated documentation example.
Highlights
- useWatch Initialization: The useWatch hook now initializes its internal state by executing the provided selector function (if it's a function) on the initial render. This ensures that the watched value is immediately available and consistent with the form's initial state.
- Documentation Example: A new example has been added to docs/examples/useWatch-selector.tsx to demonstrate the updated initialization behavior and usage of the useWatch hook with a selector.
- Code Refinement: A minor refactoring was applied to the triggerUpdate function in src/useWatch.ts to simplify a conditional expression, improving code readability.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #762 +/- ##
=======================================
Coverage 99.53% 99.53%
=======================================
Files 19 19
Lines 1287 1288 +1
Branches 319 316 -3
=======================================
+ Hits 1281 1282 +1
Misses 6 6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces an improvement to the useWatch
hook by initializing its state when a selector function is used. This ensures that the hook returns a more predictable value on the initial render, derived from an empty store, rather than undefined
. The change in src/useWatch.ts
is well-implemented. The new example in docs/examples/useWatch-selector.tsx
is helpful for demonstrating this, but it includes a console.log
statement which should be removed for code cleanliness.
docs/examples/useWatch-selector.tsx
Outdated
export default () => { | ||
const [form] = Form.useForm<FieldType>(); | ||
const base = Form.useWatch(values => ({ newName: values.name }), form); | ||
console.log('base', base); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (4)
docs/examples/useWatch-selector.tsx (4)
1-1
: 不建议全局关闭 no-shadow,直接避免同名遮蔽即可移除全局
eslint-disable
,通过重命名变量解决遮蔽问题更安全。见下方重命名建议。-/* eslint-disable @typescript-eslint/no-shadow */
14-16
: 示例中的 console.log 建议只在开发环境打印或移除避免示例页面在生产文档中产生噪声输出。
- console.log('base', base); + if (process.env.NODE_ENV !== 'production') { + // 示例调试输出 + console.log('base', base); + }
17-22
: 通过重命名外层变量避免与 selector 参数同名,移除 no-shadow 关闭重命名外层
values
,即可删除顶部的eslint-disable
。- const values = Form.useWatch( + const watchedValues = Form.useWatch( values => ({ init: values.init, newName: values.name, newAge: values.age }), { form, preserve: true }, ); - console.log('values', values); + console.log('values', watchedValues);
38-39
: 配合重命名,同步更新渲染展示;并可提升可读性可用
JSON.stringify
的缩进参数增强可读性。- values:{JSON.stringify(values)} + values: + {JSON.stringify(watchedValues, null, 2)}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/examples/useWatch-selector.tsx
(2 hunks)src/useWatch.ts
(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
docs/examples/useWatch-selector.tsx (1)
.eslintrc.js (1)
base
(1-1)
🔇 Additional comments (1)
src/useWatch.ts (1)
120-124
: 分支选择逻辑语义正确仅格式化调整,
preserve
分支与非preserve
分支的兜底获取逻辑保持不变,无功能性回归。
src/useWatch.ts
Outdated
const [value, setValue] = useState<any>( | ||
typeof dependencies === 'function' ? dependencies({}) : undefined, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
避免在渲染期间每次都执行 selector,且防止初始空对象导致崩溃
- 这里直接执行
dependencies({})
属于非惰性初始化:每次渲染都会调用 selector,有性能隐患。 - 若 selector 存在深链访问(如
values.user.profile.name
),传入{}
可能在初次渲染直接抛错,造成不可恢复的渲染失败。
建议改为惰性初始化并用 try/catch 兜底,仅在首渲染执行一次;失败时回退为 undefined
,由后续 triggerUpdate
补齐值。
- const [value, setValue] = useState<any>(
- typeof dependencies === 'function' ? dependencies({}) : undefined,
- );
+ const [value, setValue] = useState<any>(() => {
+ if (typeof dependencies === 'function') {
+ try {
+ return dependencies({} as any);
+ } catch {
+ return undefined;
+ }
+ }
+ return undefined;
+ });
可选优化(如需“首屏即有表单初值”而非 {}
):在拿到 formInstance
后用其 getFieldsValue
进行惰性初始化(需要将 useContext(FieldContext)
等取到 formInstance
的逻辑前移到 useState
之前)。
// 仅为思路示例:确保 hooks 顺序稳定
const fieldContext = useContext(FieldContext);
const formInstance = (form as InternalFormInstance) || fieldContext;
const isValidForm = formInstance && formInstance._init;
const [value, setValue] = useState<any>(() => {
if (typeof dependencies === 'function' && isValidForm) {
const initial = options.preserve
? formInstance.getFieldsValue(true)
: formInstance.getFieldsValue();
try {
return dependencies(initial);
} catch {
return undefined;
}
}
return undefined;
});
@gemini-code-assist Review it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
这个 PR 修复了 useWatch
在使用选择器函数作为依赖时,初始渲染时返回值不正确的问题。通过在 useState
初始化时使用选择器函数处理一个空对象来生成初始值,确保了初始渲染的一致性。相关的示例和测试用例也已更新,以验证此修复。
我的主要反馈是,直接用空对象调用选择器函数可能不够健壮,如果选择器函数期望特定的数据结构,可能会导致运行时崩溃。我建议增加一个 try-catch
来提高代码的容错性。
Summary by CodeRabbit
新功能
Bug 修复
文档